﻿using EnvDTE;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Axiom.CodeManifold
{
	public static class SolutionExtensions
	{
		public static Project GetProject(this EnvDTE.Solution solution, string name)
		{
			return solution.Projects.GetSolutionProjects()[name];
		}

		public static Project GetProject(this EnvDTE.DTE dte, string name)
		{
			return dte.Solution.Projects.GetSolutionProjects()[name];
		}

		public static ProjectCodeModel GetProjectItem(this EnvDTE.DTE dte, string projectname, string itemname)
		{
			ProjectCodeModel result = null;

			var project = dte.Solution.GetProject(projectname);

			ProjectItem item = project.GetProjectItem(itemname);

			if (item != null)
			{
				result = new ProjectCodeModel()
				{
					FileCodeModel = item.FileCodeModel,
					Project = project,
					Item = item,
				};
			}

			return result;
		}

		public static IDictionary<string, Project> GetSolutionProjects(this EnvDTE.DTE dte)
		{
			var result = new Dictionary<string, Project>();

			foreach (Project project in dte.Solution.Projects)
			{
				GetSolutionProjectsRecursive(project, result);
			}

			return result;
		}

		private static void GetSolutionProjectsRecursive(Project project, Dictionary<string, Project> result)
		{
			if (project.Kind == "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}") // Solution Folder - Project Item Kind
			{
				foreach (ProjectItem item in project.ProjectItems)
				{
					if (item.SubProject != null)
					{
						GetSolutionProjectsRecursive(item.SubProject, result);
					}
				}
			}
			else
			{
				result.Add(project.Name, project);
			}
		}

		public static IDictionary<string, ServiceDefinition> GetServiceDefinitions(this EnvDTE.DTE dte, string @namespace)
		{
			var result = new Dictionary<string, ServiceDefinition>();

			var project = dte.GetProject(@namespace);
			var models = project.GetCodeModels();

			Parallel.ForEach(models.Values, a =>
			{
				var interfaces = a.GetEntities<CodeInterface>();
				foreach (var @interface in interfaces)
				{
					var def = new ServiceManager(@interface);
					result.Add(def.Service.Name, def.Service);
				}
			});

			return result;
		}

		public static bool ContainsProject(this EnvDTE.DTE dte, string name)
		{
			bool result = false;

			if (dte == null || dte.Solution == null)
			{
				return false;
			}
			else
			{
				var project = GetProject(dte, name);
				result = project != null;
			}
			return result;
		}
	}
}
